/*
*	(*^。^*) TFrameWork License (*^。^*)
*/

/*
 *  Title :  
 *          
 *  Description :  
 *          
 *          
 *  Date : 
 *
 *  Author : DengPing
 *
 *  Modify : 
 */

using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

namespace TFrameWork.Module.ActionEditor
{
    public class SignalEventItemStyle : TrackItemStyleBase
    {
        protected override string eventFullName =>"SignalEventItem.uxml";
        //单个信号标记宽度为6像素
        private const int halfPointSize = 4;
        
        private VisualElement DurationSize;
        private Label SingalName;

        public bool isInit { get; private set; }

        private SignalEvent _data;
 
        public override TrackEventBase eventData => _data;
        
        private SignalTrackStyle.CommonChildTrackBase _parent;

        public void Init(SignalTrackStyle.CommonChildTrackBase parent, SignalEvent data)
        {
            this._parent = parent;
            _data = data;
            if (!isInit)
            {
                root = ActionEditorUtility.GetStyleSheet<VisualTreeAsset>(eventFullName).Instantiate().Query()
                    .ToList()[1];
                LeftPoint = root.Q(nameof(LeftPoint));
                RightPoint = root.Q(nameof(RightPoint));
                DurationSize = root.Q(nameof(DurationSize));
                SingalName = root.Q<Label>(nameof(SingalName));
                _parent.AddContent(this);
                
                //左右的拖动操作
                LeftPoint.RegisterCallback<MouseDownEvent>(LeftPointMouseDown);
                LeftPoint.RegisterCallback<MouseUpEvent>(LeftPointMouseUp);
                LeftPoint.RegisterCallback<MouseMoveEvent>(LeftPointMouseMove);

                RightPoint.RegisterCallback<MouseDownEvent>(RightPointMouseDown);
                RightPoint.RegisterCallback<MouseUpEvent>(RightPointMouseUp);
                RightPoint.RegisterCallback<MouseMoveEvent>(RightPointMouseMove);

                root.RegisterCallback<MouseDownEvent>(RootMouseDown);
                root.RegisterCallback<MouseUpEvent>(RootMouseUp);
                root.RegisterCallback<MouseMoveEvent>(RootMouseMove);

                DurationSize.RegisterCallback<MouseDownEvent>(DurationSizeMouseDown);
                DurationSize.RegisterCallback<MouseUpEvent>(DurationSizeMouseUp);
                DurationSize.RegisterCallback<MouseMoveEvent>(DurationSizeMouseMove);

                // 创建右键菜单
                var menu = new ContextualMenuManipulator(evt =>
                {
                    _parent.addState = DropdownMenuAction.Status.Disabled;
                    evt.menu.AppendAction("删除", DeleteEvent, DropdownMenuAction.AlwaysEnabled);
                });
                var menu2 = new ContextualMenuManipulator(evt =>
                {
                    _parent.addState = DropdownMenuAction.Status.Disabled;
                    evt.menu.AppendAction("删除", DeleteEvent, DropdownMenuAction.AlwaysEnabled);
                });
                var menu3 = new ContextualMenuManipulator(evt =>
                {
                    _parent.addState = DropdownMenuAction.Status.Disabled;
                    evt.menu.AppendAction("删除", DeleteEvent, DropdownMenuAction.AlwaysEnabled);
                });

                LeftPoint.AddManipulator(menu);
                RightPoint.AddManipulator(menu2);
                DurationSize.AddManipulator(menu3);


                isInit = true;
            }


            ResetView();
        }

        private void DeleteEvent(DropdownMenuAction obj)
        {
            _parent.DeleteEvent(this);
        }

        #region 拖动操作

        //是否拖拽
        private bool mouseDrag = false;
        private bool drationLeftDrag = false;
        private bool drationRightDrag = false;
        private float leftOffset = 0;
        private float movePositionX = -1;
        private float drationOffset = 0;

        private void LeftPointMouseDown(MouseDownEvent evt)
        {
            if (_data.isDuration)
            {
                movePositionX = -1;
                ActionEditor.Instance.MouseUpEvent += LeftPointMouseUp;
                ActionEditor.Instance.MouseMoveEvent += LeftPointMouseMove;
                ActionEditor.Instance.MouseOutEvent += LeftPointMouseOut;

                drationLeftDrag = true;
            }

        }

        private void LeftPointMouseUp(MouseUpEvent evt)
        {
            if (_data.isDuration)
            {
                ActionEditor.Instance.MouseUpEvent -= LeftPointMouseUp;
                ActionEditor.Instance.MouseMoveEvent -= LeftPointMouseMove;
                ActionEditor.Instance.MouseOutEvent -= LeftPointMouseOut;
                ApplayDurationMove(true);
                drationLeftDrag = false;
            }
        }

        private void LeftPointMouseMove(MouseMoveEvent evt)
        {
            if (_data.isDuration && drationLeftDrag)
            {
                var localPosition = _parent.trackEventContent.WorldToLocal(evt.mousePosition);
                movePositionX = localPosition.x;

                var currentIndex = movePositionX / ActionEditor.Instance.actionEditorConfig.frameUnitWidth;
                if (currentIndex > _data.startIndex + _data.durationIndex)
                {
                    movePositionX = (_data.startIndex + _data.durationIndex) *
                                    ActionEditor.Instance.actionEditorConfig.frameUnitWidth;
                    return;
                }

                var pos = root.transform.position;
                pos.x = movePositionX - halfPointSize;
                root.transform.position = pos;

                leftOffset = (_data.startIndex - currentIndex) * ActionEditor.Instance.actionEditorConfig.frameUnitWidth;

                //计算size
                var showSize = _data.durationIndex * ActionEditor.Instance.actionEditorConfig.frameUnitWidth + leftOffset;
                DurationSize.style.width = showSize;

            }
        }


        private void LeftPointMouseOut(MouseOutEvent evt)
        {
            if (_data.isDuration)
            {
                ActionEditor.Instance.MouseUpEvent -= LeftPointMouseUp;
                ActionEditor.Instance.MouseMoveEvent -= LeftPointMouseMove;
                ActionEditor.Instance.MouseOutEvent -= LeftPointMouseOut;
                if (drationLeftDrag) ApplayDurationMove(true);
                drationLeftDrag = false;
            }
        }


        private void RightPointMouseDown(MouseDownEvent evt)
        {
            if (_data.isDuration)
            {
                movePositionX = -1;
                ActionEditor.Instance.MouseUpEvent += RightPointMouseUp;
                ActionEditor.Instance.MouseMoveEvent += RightPointMouseMove;
                ActionEditor.Instance.MouseOutEvent += RightPointMouseOut;

                drationRightDrag = true;
            }
        }

        private void RightPointMouseUp(MouseUpEvent evt)
        {
            if (_data.isDuration)
            {
                ActionEditor.Instance.MouseUpEvent -= RightPointMouseUp;
                ActionEditor.Instance.MouseMoveEvent -= RightPointMouseMove;
                ActionEditor.Instance.MouseOutEvent -= RightPointMouseOut;
                if (drationRightDrag) ApplayDurationMove(false);
                drationRightDrag = false;
            }
        }

        private void RightPointMouseMove(MouseMoveEvent evt)
        {
            if (_data.isDuration && drationRightDrag)
            {
                var localPosition = _parent.trackEventContent.WorldToLocal(evt.mousePosition);
                movePositionX = localPosition.x;

                var currentIndex = movePositionX / ActionEditor.Instance.actionEditorConfig.frameUnitWidth;
                if (currentIndex < _data.startIndex)
                {
                    movePositionX = _data.startIndex * ActionEditor.Instance.actionEditorConfig.frameUnitWidth;
                    return;
                }

                leftOffset = (currentIndex - _data.startIndex - _data.durationIndex) *
                             ActionEditor.Instance.actionEditorConfig.frameUnitWidth;

                //计算size
                var showSize = _data.durationIndex * ActionEditor.Instance.actionEditorConfig.frameUnitWidth + leftOffset;
                DurationSize.style.width = showSize;
            }
        }

        private void RightPointMouseOut(MouseOutEvent evt)
        {
            if (_data.isDuration)
            {
                ActionEditor.Instance.MouseUpEvent -= RightPointMouseUp;
                ActionEditor.Instance.MouseMoveEvent -= RightPointMouseMove;
                ActionEditor.Instance.MouseOutEvent -= RightPointMouseOut;
                if (drationRightDrag) ApplayDurationMove(false);
                drationRightDrag = false;
            }
        }

        private void DurationSizeMouseDown(MouseDownEvent evt)
        {
            if (_data.isDuration)
            {
                var localPosition = _parent.trackEventContent.WorldToLocal(evt.mousePosition);
                drationOffset = DurationSize.WorldToLocal(evt.mousePosition).x;
                movePositionX = localPosition.x - drationOffset;
                ActionEditor.Instance.MouseUpEvent += DurationSizeMouseUp;
                ActionEditor.Instance.MouseMoveEvent += DurationSizeMouseMove;
                ActionEditor.Instance.MouseOutEvent += DurationSizeMouseOut;

                mouseDrag = true;
            }
        }

        private void DurationSizeMouseUp(MouseUpEvent evt)
        {
            if (_data.isDuration)
            {
                ActionEditor.Instance.MouseUpEvent -= DurationSizeMouseUp;
                ActionEditor.Instance.MouseMoveEvent -= DurationSizeMouseMove;
                ActionEditor.Instance.MouseOutEvent -= DurationSizeMouseOut;
                if (mouseDrag) ApplayMove();
                mouseDrag = false;
            }
        }

        private void DurationSizeMouseMove(MouseMoveEvent evt)
        {
            if (_data.isDuration && mouseDrag)
            {
                var localPosition = _parent.trackEventContent.WorldToLocal(evt.mousePosition);
                movePositionX = localPosition.x - drationOffset;
                var pos = root.transform.position;
                pos.x = movePositionX;
                root.transform.position = pos;
            }

        }

        private void DurationSizeMouseOut(MouseOutEvent evt)
        {
            if (_data.isDuration)
            {
                ActionEditor.Instance.MouseUpEvent -= DurationSizeMouseUp;
                ActionEditor.Instance.MouseMoveEvent -= DurationSizeMouseMove;
                ActionEditor.Instance.MouseOutEvent -= DurationSizeMouseOut;
                if (mouseDrag) ApplayMove();
                mouseDrag = false;
            }
        }

        private void RootMouseDown(MouseDownEvent evt)
        {
            Select();
            if (!_data.isDuration)
            {
                var localPosition = _parent.trackEventContent.WorldToLocal(evt.mousePosition);
                movePositionX = localPosition.x;

                ActionEditor.Instance.MouseUpEvent += RootMouseUp;
                ActionEditor.Instance.MouseMoveEvent += RootMouseMove;
                ActionEditor.Instance.MouseOutEvent += RootMouseOut;

                mouseDrag = true;
            }
        }

        private void RootMouseUp(MouseUpEvent evt)
        {
            if (!_data.isDuration)
            {
                ActionEditor.Instance.MouseUpEvent -= RootMouseUp;
                ActionEditor.Instance.MouseMoveEvent -= RootMouseMove;
                ActionEditor.Instance.MouseOutEvent -= RootMouseOut;
                if (mouseDrag) ApplayMove();
                mouseDrag = false;
            }
        }

        private void RootMouseMove(MouseMoveEvent evt)
        {
            if (!_data.isDuration && mouseDrag)
            {
                var localPosition = _parent.trackEventContent.WorldToLocal(evt.mousePosition);
                movePositionX = localPosition.x;
                var pos = root.transform.position;
                pos.x = movePositionX - halfPointSize;
                root.transform.position = pos;
            }
        }

        private void RootMouseOut(MouseOutEvent evt)
        {
            if (!_data.isDuration)
            {
                ActionEditor.Instance.MouseUpEvent -= RootMouseUp;
                ActionEditor.Instance.MouseMoveEvent -= RootMouseMove;
                ActionEditor.Instance.MouseOutEvent -= RootMouseOut;
                if (mouseDrag) ApplayMove();
                mouseDrag = false;
            }
        }

        private void ApplayDurationMove(bool left)
        {
            TUndo.RecordObject(_data,"ParticleEvent Size");
            _data.durationIndex += Mathf.RoundToInt(leftOffset / ActionEditor.Instance.actionEditorConfig.frameUnitWidth);
            EditorUtility.SetDirty(ActionEditor.Instance.ActionData);
            if (left)
            {
                if(movePositionX == -1) return;
                int targetIndex = Mathf.RoundToInt(movePositionX / ActionEditor.Instance.actionEditorConfig.frameUnitWidth);
                _data.startIndex = targetIndex;
                movePositionX = -1;
                EditorUtility.SetDirty(ActionEditor.Instance.ActionData);
                ResetView();
            }
            else
            {
                ResetView();
            }
        }

        private void ApplayMove()
        {
            if(movePositionX == -1) return;
            TUndo.RecordObject(_data,"SignalEvent Move");
            int targetIndex = Mathf.RoundToInt(movePositionX / ActionEditor.Instance.actionEditorConfig.frameUnitWidth);
            _data.startIndex = targetIndex;
            movePositionX = -1;
            EditorUtility.SetDirty(ActionEditor.Instance.ActionData);
            ResetView();
        }

        #endregion

        
        public override void ResetView()
        {
            if (_data.isDuration)
            {
                DurationSize.style.width = _data.durationIndex *
                                           ActionEditor.Instance.actionEditorConfig.frameUnitWidth;
                SingalName.text = _data.trackName;
            }
            else
            {
                DurationSize.style.width = 0;
            }

            var pos = root.transform.position;
            pos.x = _data.startIndex * ActionEditor.Instance.actionEditorConfig.frameUnitWidth - halfPointSize;
            root.transform.position = pos;
        }


    }
}
